/*
	Copyright (C) 2009 jungil Han <jungil.Han@gmail.com>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "mkHotkeyManager.h"
#include "../Button/mkHotkeyButton.h"
#include "../Util/mkUtil.h"

#include <QList>
#include <QObject>
#include <QApplication>
#include <QtAlgorithms>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <qt_windows.h>
//#include <QMessageBox>

mkHotkeyManager* mkHotkeyManager::s_pThis = NULL;

mkHotkeyManager* mkHotkeyManager::Instance()
{
	if (!s_pThis)
		s_pThis = new mkHotkeyManager();

	return s_pThis;
}

void mkHotkeyManager::SetParent( IN QObject *a_pParent )
{
	m_pParent = a_pParent;
}

void mkHotkeyManager::LoadfromFile()
{
	QString strWriteDir;
	mkUtil::GetWriteDir( strWriteDir );

	QFile loadFile( strWriteDir + "Monkey Config.txt" );
	if ( !loadFile.open( QIODevice::ReadOnly | QIODevice::Text ))
		 return;

	//QMessageBox::information( QApplication::activeWindow(), "ezHotkeyManager::LoadFromFile",  strWriteDir + "Monkey Config.txt" );

	QTextStream inStream( &loadFile );

	while( !inStream.atEnd() ) {
		QString strLine = inStream.readLine();
		ParseHotkeyInfo( strLine );
	}

	loadFile.close();

#if 0
	// For debug
	QString strHotkeyInfo;
	QList<mkHotkeyInfo>::iterator it;
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		strHotkeyInfo += QString( "[%1] %2 %3 %4\n" ).arg( it->nButtonID ).arg( it->nSystemKey ).arg( it->nNonSystemKey ).arg( it->strFileName );
	}
	QMessageBox::information( QApplication::activeWindow(), "ezHotkeyManager::Load",  strHotkeyInfo );	
#endif	
}

void mkHotkeyManager::SavetoFile()
{
	QString strWriteDir;
	mkUtil::GetWriteDir( strWriteDir );

	QFile saveFile( strWriteDir + "Monkey Config.txt" );
	if ( !saveFile.open( QIODevice::WriteOnly | QIODevice::Text ))
		 return;

	//QMessageBox::information( QApplication::activeWindow(), "ezHotkeyManager::SaveToFile",  strWriteDir + "Monkey Config.txt" );

	SortByID();
	
	QTextStream outStream( &saveFile );

	QList<mkHotkeyInfo>::iterator it;
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		outStream << it->nButtonID << "|";
		outStream << it->nSystemKey << "|";
		outStream << it->nNonSystemKey << "|";
		outStream << it->strFileName << "|" << endl;
	}

	saveFile.close();
}

void mkHotkeyManager::AddHotkey( IN int a_nButtonID, IN int a_nSystemKey, IN int a_nNonSystemKey, IN QString a_strFileName )
{
	mkHotkeyInfo hotkeyInfo;

	hotkeyInfo.nButtonID = a_nButtonID;
	hotkeyInfo.nSystemKey = a_nSystemKey;
	hotkeyInfo.nNonSystemKey = a_nNonSystemKey;
	hotkeyInfo.strFileName = a_strFileName;

	RemoveHotkeyAt( a_nButtonID );

	m_hotkeyInfoList.append( hotkeyInfo );

#if 0
	// For debug
	SortByID();
	QList<mkHotkeyInfo>::iterator it;
	QString strHotkeyInfo;
	
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		strHotkeyInfo += QString( "[%1] %2 %3 %4\n" ).arg( it->nButtonID ).arg( it->nSystemKey ).arg( it->nNonSystemKey ).arg( it->strFileName );
	}
	QMessageBox::information( QApplication::activeWindow(), "DEBUG",  strHotkeyInfo );	
#endif	
}

void mkHotkeyManager::RemoveHotkeyAt( IN int a_nButtonID )
{
	UnregisterHotkeyAt( a_nButtonID );

	QList<mkHotkeyInfo>::iterator it;
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		if ( it->nButtonID == a_nButtonID ) {
			m_hotkeyInfoList.erase( it );
		}
	}

#if 0
	// For debug
	QString strHotkeyInfo;	
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		strHotkeyInfo += QString( "[%1] %2 %3 %4\n" ).arg( it->nButtonID ).arg( it->nSystemKey ).arg( it->nNonSystemKey ).arg( it->strFileName );
	}
	QMessageBox::information( QApplication::activeWindow(), "After DelHotkey",  strHotkeyInfo );	
#endif		
}

void mkHotkeyManager::RemoveHotkeyAll()
{
	UnregisterHotkeyAll();
	
	m_hotkeyInfoList.erase( m_hotkeyInfoList.begin(), m_hotkeyInfoList.end() );
}

void mkHotkeyManager::RegisterHotkeyAt( IN int a_nButtonID )
{
	QList<mkHotkeyInfo>::iterator it;

	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		if ( it->nButtonID == a_nButtonID ) {
			WId hWnd = static_cast<QWidget*>( m_pParent )->winId();
			RegisterHotKey( hWnd, it->nButtonID,
					mkUtil::TranslateKeyQtToWin32( (Qt::Key)it->nSystemKey ),
							mkUtil::TranslateKeyQtToWin32( (Qt::Key)it->nNonSystemKey ));
			break;
		}
	}
}

void mkHotkeyManager::RegisterHotkeyAll()
{
	QList<mkHotkeyInfo>::iterator it;

	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		WId hWnd = static_cast<QWidget*>( m_pParent )->winId();
		RegisterHotKey( hWnd, it->nButtonID,
				mkUtil::TranslateKeyQtToWin32( (Qt::Key)it->nSystemKey ),
				mkUtil::TranslateKeyQtToWin32( (Qt::Key)it->nNonSystemKey ));
	}
}

void mkHotkeyManager::UnregisterHotkeyAt( IN int a_nButtonID )
{
	QList<mkHotkeyInfo>::iterator it;
	
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		if ( it->nButtonID == a_nButtonID ) {
			WId hWnd = static_cast<QWidget*>( m_pParent )->winId();
			UnregisterHotKey( hWnd, it->nButtonID );
			break;
		}
	}
}

void mkHotkeyManager::UnregisterHotkeyAll()
{
	QList<mkHotkeyInfo>::iterator it;
	
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		WId hWnd = static_cast<QWidget*>( m_pParent )->winId();
		UnregisterHotKey( hWnd, it->nButtonID );
	}
}
	
QString mkHotkeyManager::GetFileName( IN int a_nSystemKey, IN int a_nNonSystemKey )
{
	QString strFileName;

	QList<mkHotkeyInfo>::iterator it;
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		if ( it->nSystemKey == a_nSystemKey && it->nSystemKey == a_nNonSystemKey ) {
			    strFileName = it->strFileName;
		}
	}

	return strFileName;
}

const QList<mkHotkeyInfo> mkHotkeyManager::GetList()
{
	return m_hotkeyInfoList;
}

void mkHotkeyManager::ParseHotkeyInfo( IN QString &a_refHotkeyInfo )
{
	QStringList strList;
	strList = a_refHotkeyInfo.split( "|" );

	mkHotkeyInfo hotkeyInfo;
	
	for ( int nIndex = 0; nIndex < strList.size(); ++nIndex ) {
		switch ( nIndex ) {
			case 0:
			{
				QString strButtonID = strList.at( nIndex ).toLocal8Bit().constData();
				hotkeyInfo.nButtonID = strButtonID.toInt();
				break;
			}
			case 1:
			{
				QString strSystemKey = strList.at( nIndex ).toLocal8Bit().constData();
				hotkeyInfo.nSystemKey = strSystemKey.toInt();
				break;				
			}	
			case 2:
			{
				QString strNonSystemKey = strList.at( nIndex ).toLocal8Bit().constData();
				hotkeyInfo.nNonSystemKey = strNonSystemKey.toInt();				
				break;
			}	
			case 3:
			{
				//QTextCodec *codec = QTextCodec::codecForName("EUC-KR");
				//hotkeyInfo.strFileName = strList.at( nIndex ).toLocal8Bit().constData();				
				QTextCodec *codec = QTextCodec::codecForLocale ();
				hotkeyInfo.strFileName = codec->toUnicode( strList.at( nIndex ).toLocal8Bit() );	
				break;
			}	
			default:
				break;
		}	
	}

	m_hotkeyInfoList.append( hotkeyInfo );	
}

void mkHotkeyManager::SortByID()
{
	qSort( m_hotkeyInfoList.begin(), m_hotkeyInfoList.end(), LessThanID );
}

bool mkHotkeyManager::LessThanID( const mkHotkeyInfo &a_refHotkey1, const mkHotkeyInfo &a_refHotkey2 )
{
	return a_refHotkey1.nButtonID < a_refHotkey2.nButtonID;
}

void mkHotkeyManager::SortByHotkey()
{
	qSort( m_hotkeyInfoList.begin(), m_hotkeyInfoList.end(), MoreThanHotkey );

	for ( int nIndex = 0; nIndex < m_hotkeyInfoList.size(); nIndex++ ) {
		mkHotkeyInfo hotkeyInfo = m_hotkeyInfoList.takeFirst();
		hotkeyInfo.nButtonID = nIndex + 1;
		m_hotkeyInfoList.append( hotkeyInfo );
	}

#if 0
	// For debug
	QString strHotkeyInfo;
	QList<mkHotkeyInfo>::iterator it;
	for ( it = m_hotkeyInfoList.begin(); it < m_hotkeyInfoList.end(); it++ ) {
		strHotkeyInfo += QString( "[%1] %2 %3 %4\n" ).arg( it->nButtonID ).arg( it->nSystemKey ).arg( it->nNonSystemKey ).arg( it->strFileName );
	}
	QMessageBox::information( QApplication::activeWindow(), "SortByHotkey",  strHotkeyInfo );	
#endif		
}

bool mkHotkeyManager::MoreThanHotkey( const mkHotkeyInfo &a_refHotkey1, const mkHotkeyInfo &a_refHotkey2 )
{
	bool bResult = false;
	
	if ( a_refHotkey1.nSystemKey == a_refHotkey2.nSystemKey )
		bResult = a_refHotkey1.nNonSystemKey < a_refHotkey2.nNonSystemKey;
	else {
		/* Key_Alt: 0x01000023, Key_Meta: 0x01000022, Key_Ctrl: 0x01000021, Key_Shift: 0x01000020 */
		if ( a_refHotkey1.nSystemKey == Qt::Key_Meta )
			bResult = false;
		else if ( a_refHotkey2.nSystemKey == Qt::Key_Meta )
			bResult = true;
		else 
			bResult = a_refHotkey1.nSystemKey > a_refHotkey2.nSystemKey;
	}

	return bResult;
}
